SwiftUIでSearchBarが使いたいので自作する
SwiftUIでUISearchBar
のようなものが使いたかったので自作することにしました。
環境
- Xcode 13.3
はじめに
2022年4月時点でSearchBar
というようなViewはSwiftUIの標準では存在しておりません。その代わりiOS 15以降ではsearchable(text:placement:)
というモディファイアを使うことができ、SearchBar
のような動きをしてくれます。
iOS 15からという条件もそうなのですが、2022年4月22日時点ではBetaの記載があり、またこのモディファイアはNavigationView
をラップしなければ表示できません。
NavigationView無し
struct ContentView: View { @State private var searchText = "" var body: some View { Text("SearchBar↑") .searchable(text: $searchText) } }
結果
SearchBar
表示されません。
)
NavigationView有り
struct ContentView: View { @State private var searchText = "" var body: some View { NavigationView { Text("SearchBar↑") .searchable(text: $searchText) } } }
結果
SearchBar
が表示されました。
これで検索を行えるようになりました!しかし、NavigationView
をラップしないと使えないというのは少し不便ですね。
SearchBarを自作する
NavigationView
がない場所でも気軽にSearchBar
を気軽に使いたいので自分で作ってみることにしました。
import SwiftUI struct SearchBar: View { @Binding var text: String var body: some View { VStack { ZStack { // 背景 RoundedRectangle(cornerRadius: 8) .fill(Color(red: 239 / 255, green: 239 / 255, blue: 241 / 255)) .frame(height: 36) HStack(spacing: 6) { Spacer() .frame(width: 0) // 虫眼鏡 Image(systemName: "magnifyingglass") .foregroundColor(.gray) // テキストフィールド TextField("Search", text: $text) // 検索文字が空ではない場合は、クリアボタンを表示 if !text.isEmpty { Button { text.removeAll() } label: { Image(systemName: "xmark.circle.fill") .foregroundColor(.gray) } .padding(.trailing, 6) } } } .padding(.horizontal) } } }
標準のsearchable
と比較してみましょう。
上側が、標準のSearchable
で、下側が自作のSearchBar
です。
見た目的にも同じように作成出来ました!しかし、プレースホルダーのカラーの違いが少し気になるので変えていきます。
プレースホルダーのカラーを変更する
2022年4月時点では、プレースホルダーの色を変更するAPIはまだ無さそうなので自作のプレースホルダーモディファイアを作成します。
extension View { func placeholder<Content: View>( when shouldShow: Bool, alignment: Alignment = .leading, color: Color, @ViewBuilder placeholder: () -> Content) -> some View { ZStack(alignment: alignment) { placeholder() .opacity(shouldShow ? 1 : 0) .foregroundColor(color) self } } }
- when shouldShow
- いつプレースホルダーを表示するか
- alignment
- プレースホルダーのalignmentです。基本的には
.leading
でいいと思います。
- プレースホルダーのalignmentです。基本的には
- color
- プレースホルダーのカラー
- @ViewBuilder placeholder
- placeHolderとして使用するViewを受け取ります。
自作プレースホルダーを使う
下記のようにTextField
と一緒に使用します。TextField
の元々のプレースホルダーは使用しないので空にしておき、自作したプレースホルダーのコンテンツとしてText("Search")
を入れています。color
は標準Searchableのプレースホルダーの色味に近かった.gray
にしました。
TextField("", text: $text) .placeholder(when: text.isEmpty, color: .gray) { Text("Search") }
標準のsearchable
と比較してみましょう。
さらに標準Searchableの雰囲気に近づけることが出来ました。
完成版
完成版のコードはGitHubに上げています。
動かすとこんな感じになります。searchable
にそっくりな自家製のSearchBar
を作ることが出来ました!
おわりに
ライブラリにする必要まではなさそうですが、時折使えそうなのでコードスニペットとして登録しておいて使いたい時に瞬時に使えるようにすると良さそうですね。